package com.diver.flinkdemo.utils;

import com.alibaba.fastjson.JSONArray;
import org.apache.commons.collections4.CollectionUtils;

import java.util.List;

/**
 * 判断某个点是否在所画区域内
 */
public class RangeCompareUtil {

    /**
     * 判断点是否在多边形内
     *
     * @param point 检测点
     * @param pts   多边形的顶点
     * @return 点在多边形内返回true, 否则返回false
     */
    public static boolean isPtInPoly(Point2D point, List<Point2D> pts) {

        int N = pts.size();
        boolean boundOrVertex = true; // 如果点位于多边形的顶点或边上，也算做点在多边形内，直接返回true
        int intersectCount = 0;// cross points count of x
        double precision = 2e-10; // 浮点类型计算时候与0比较时候的容差
        Point2D p1, p2;// neighbour bound vertices
        Point2D p = point; // 当前点

        p1 = pts.get(0);
        for (int i = 1; i <= N; ++i) {
            if (p.equals(p1)) {
                return boundOrVertex;
            }

            p2 = pts.get(i % N);
            if (p.lon < Math.min(p1.lon, p2.lon) || p.lon > Math.max(p1.lon, p2.lon)) {
                p1 = p2;
                continue;
            }

            if (p.lon > Math.min(p1.lon, p2.lon) && p.lon < Math.max(p1.lon, p2.lon)) {
                if (p.lat <= Math.max(p1.lat, p2.lat)) {
                    if (p1.lon == p2.lon && p.lat >= Math.min(p1.lat, p2.lat)) {
                        return boundOrVertex;
                    }

                    if (p1.lat == p2.lat) {
                        if (p1.lat == p.lat) {
                            return boundOrVertex;
                        } else {
                            ++intersectCount;
                        }
                    } else {
                        double xinters = (p.lon - p1.lon) * (p2.lat - p1.lat) / (p2.lon - p1.lon) + p1.lat;
                        if (Math.abs(p.lat - xinters) < precision) {
                            return boundOrVertex;
                        }

                        if (p.lat < xinters) {
                            ++intersectCount;
                        }
                    }
                }
            } else {
                if (p.lon == p2.lon && p.lat <= p2.lat) {
                    Point2D p3 = pts.get((i + 1) % N);
                    if (p.lon >= Math.min(p1.lon, p3.lon) && p.lon <= Math.max(p1.lon, p3.lon)) {
                        ++intersectCount;
                    } else {
                        intersectCount += 2;
                    }
                }
            }
            p1 = p2;
        }

        if (intersectCount % 2 == 0) {// 偶数在多边形外
            return false;
        } else { // 奇数在多边形内
            return true;
        }

    }


    public static void main(String[] args) {
        Point2D point = new Point2D(104.072868, 30.539073);
        // 测试一个点是否在多边形内
//		List<Point2D> pts = new ArrayList<Point2D>();
//		pts.add(new Point2D(104.074757, 30.658143));
//		pts.add(new Point2D(104.093442, 30.658454));
//		pts.add(new Point2D(104.09301, 30.64584));
//		pts.add(new Point2D(104.083884, 30.648636));
//		pts.add(new Point2D(104.075476, 30.64236));
        String latlonjosn = "[{\"lon\":104.073502,\"lat\":30.53744},{\"lon\":104.073351,\"lat\":30.542416},{\"lon\":104.069678,\"lat\":30.54237},{\"lon\":104.069978,\"lat\":30.537292}]";
        List<Point2D> pts = JSONArray.parseArray(latlonjosn, Point2D.class);
        if (isPtInPoly(point, pts)) {
            System.out.println("点在多边形内");
        } else {
            System.out.println("点在多边形外");
        }
    }


    public static Integer calculatePoint(String lon, String lat, String latlonjosn) {
        Point2D point = new Point2D(Double.parseDouble(lon), Double.parseDouble(lat));
        List<Point2D> pts = JSONArray.parseArray(latlonjosn, Point2D.class);
        if(CollectionUtils.isNotEmpty(pts)) {
            if (isPtInPoly(point, pts)) {
//			System.out.println("点在多边形内");
                return 1;
            } else {
//			System.out.println("点在多边形外");
                return 0;
            }
        }
        return 0;
    }

}